<template>
  <div class="login">
    <!-- 登录框 -->
    <el-card class="box-card">
      <div class="text item">
        <el-form
          :model="loginForm"
          status-icon
          :rules="rules"
          ref="loginForm"
          label-width="100px"
          class="demo-ruleForm"
        >
          <el-form-item label="用户名" prop="username">
            <el-input
              v-model="loginForm.username"
              placeholder="请输入用户名"
            ></el-input>
          </el-form-item>
          <el-form-item label="密码" prop="password">
            <el-input
              type="password"
              v-model="loginForm.password"
              autocomplete="off"
              placeholder="请输入密码"
            ></el-input>
          </el-form-item>
          <el-form-item label="" prop="checkbox">
            <el-checkbox
              label="记住密码(可用)"
              name="type"
              v-model="loginForm.state"
            ></el-checkbox>
          </el-form-item>

          <el-form-item>
            <el-button type="primary" @click="submitForm('loginForm')"
              >登 录
            </el-button>
            <el-button @click="resetForm('loginForm')">注 册</el-button>
          </el-form-item>
        </el-form>
      </div>
    </el-card>

    <!-- 点击注册时打开弹窗 -->
    <!--   @close="onDialogClosed"当关闭对话框时触发 -->
    <el-dialog
      title="注册"
      :visible.sync="dialogVisible"
      width="500px"
      @close="onDialogClosed"
    >
      <el-form
        :label-position="labelPosition"
        label-width="80px"
        :model="registerForm"
        status-icon
        :rules="rules"
        ref="registerForm"
      >
        <el-form-item label="用户名" prop="name">
          <!-- @input="examine" 当表单内容发生变化时 发起ajax请求验证用户名是否可用 -->
          <el-input
            v-model="registerForm.name"
            placeholder="请输入用户名"
            @input="examine"
          ></el-input>
        </el-form-item>
        <el-form-item prop="email" label="邮箱" placeholder="请输入邮箱地址">
          <el-input v-model="registerForm.email" @input="examine"></el-input>
        </el-form-item>
        <el-form-item label="密码" prop="pass">
          <el-input
            type="password"
            v-model="registerForm.pass"
            autocomplete="off"
          ></el-input>
        </el-form-item>
        <el-form-item label="确认密码" prop="checkPass">
          <el-input
            type="password"
            v-model="registerForm.checkPass"
            autocomplete="off"
          ></el-input>
        </el-form-item>

        <!-- 验证码组件 -->

        <el-form-item label="验证码" prop="Identification">
          <el-input
            v-model="registerForm.Identification"
            autocomplete="off"
            style="width: 120px; float: left"
          ></el-input>
          <div class="box" style="width: 15px; height: 15px; float: left"></div>
          <!-- 调用更换验证事件 -->
          <div @click="refreshCode" style="cursor: pointer">
            <s-identify :identifyCode="registerForm.identifyCode"></s-identify>
          </div>
        </el-form-item>
      </el-form>

      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false"> 取 消 </el-button>
        <el-button type="primary" @click="submitFormLabelAlign('registerForm')"
          >注 册</el-button
        >
      </span>
    </el-dialog>
  </div>
</template>

<script>
import SIdentify from '../../components/Identification/ldentification.vue' // 导入验证码组件

import { loading } from 'element-ui' // 添加 loading效果
let loadingInstance = null // 定义关闭 loading效果
// import _ from 'lodash' // 引入节流和防抖 全部引入
import throttle from 'lodash/throttle' // 引入节流 按需引入
import debounce from 'lodash/debounce' // 引入防抖
// console.log(debounce)
// npm install --save js-base64
const Base64 = require('js-base64').Base64 // 导入base64对保存在浏览器的密码加密
// console.log(Base64)

export default {
  name: 'MyLogin',
  components: {
    SIdentify
  },
  data() {
    // 表单验证
    var validateUser = (rule, value, callback) => {
      if (value === '') {
        callback(new Error('请输入用户名'))
      } else {
        if (this.RegisteredUser === false) {
          callback(new Error('用户已经存在'))
        }
        callback()
      }
    }

    var validateEmail = (rule, value, callback) => {
      if (value === '') {
        callback(new Error('请输入邮箱'))
      } else {
        if (this.RegisteredEmail === false) {
          callback(new Error('邮箱已经存在'))
        }
        callback()
      }
    }
    var validatePass = (rule, value, callback) => {
      if (value === '') {
        callback(new Error('请输入密码'))
      } else {
        if (this.registerForm.checkPass !== '') {
          this.$refs.registerForm.validateField('checkPass')
        }
        callback()
      }
    }
    var validatePass2 = (rule, value, callback) => {
      if (value === '') {
        callback(new Error('请再次输入密码'))
      } else if (value !== this.registerForm.pass) {
        callback(new Error('两次输入密码不一致!'))
      } else {
        callback()
      }
    }
    var Identification = (rule, value, callback) => {
      // 将验证码表单 和 验证码 转为小写 当用户输入大写或者小写都可以通过验证
      let valueLowercase = value.toLowerCase()
      let identifyCodeLowercase = this.registerForm.identifyCode.toLowerCase()
      // console.log(valueLowercase, identifyCodeLowercase)

      if (value === '') {
        callback(new Error('请再次输入验证码'))
      } else if (valueLowercase !== identifyCodeLowercase) {
        // 重新切换验证码
        this.refreshCode()
        callback(new Error('验证码错误'))
      } else {
        callback()
      }
    }
    return {
      // 控制是否开启注册的ialog 对话框
      dialogVisible: false,

      // 注册对话框里的表单
      labelPosition: 'right',
      registerForm: {
        name: '',
        region: '',
        type: '',
        email: '',
        pass: '',
        checkPass: '',
        Identification: '',
        // 验证码随机数
        identifyCodes:
          '1234567890ABCDEFGHIGKLMNoPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz',
        // 验证码初始值
        identifyCode: ''
      },

      // 登录的用户名和密码，记住密码
      loginForm: {
        username: '',
        password: '',
        // 记住密码的复选框的状态如果为true，向浏览器中存储token值，记住密码
        state: false
      },

      // 表单验证
      rules: {
        // 登录
        username: [
          { required: true, message: '请输入用户名', trigger: 'blur' },
          { min: 3, max: 6, message: '长度在 3 到 6 个字符', trigger: 'blur' }
        ],
        password: [
          { required: true, message: '请输入密码', trigger: 'blur' },
          { min: 3, max: 12, message: '长度在 3 到 12 个字符', trigger: 'blur' }
        ],
        // 注册
        name: [
          { required: true, validator: validateUser, trigger: 'blur' },
          { min: 3, max: 6, message: '长度在 3 到 6 个字符', trigger: 'blur' }
        ],
        pass: [
          { required: true, validator: validatePass, trigger: 'blur' },
          { min: 3, max: 12, message: '长度在 3 到 12 个字符', trigger: 'blur' }
        ],
        checkPass: [
          { required: true, validator: validatePass2, trigger: 'blur' }
        ],
        email: [
          { required: true, validator: validateEmail, trigger: 'blur' },
          {
            type: 'email',
            message: '请输入正确的邮箱地址',
            trigger: ['blur', 'change']
          }
        ],
        Identification: [
          { required: true, validator: Identification, trigger: 'blur' }
        ]
      }
    }
  },
  computed: {
    //  登录时 该值从 服务端返回来的token值 存储了用户的唯一标识 如果不为空则登录成功
    token() {
      return this.$store.state.login.token
    },
    // 登录时 从服务端返回的判断是否存在该用户 true 存在 false 不存在
    user() {
      return this.$store.state.login.user
    },
    // 注册时 检测用户名是否可用
    RegisteredUser() {
      return this.$store.state.register.username
    },
    // 注册时 检测邮箱是否可用
    RegisteredEmail() {
      return this.$store.state.register.email
    }
  },
  mounted() {
    // 验证码初始化
    this.identifyCode = ''
    this.makeCode(this.registerForm.identifyCodes, 4)
    // 如果勾选了记住密码将保存在浏览器的密码进行回显
    this.getCookie()
  },
  methods: {
    // 用户登录(添加了节流函数)，在这里向服务端发送登录请求
    submitForm: throttle(function (formName) {
      this.$refs[formName].validate(async (valid) => {
        if (valid) {
          // 发送请求 跟服务器确认有没有该用户 当服务端返回登录用户的token值时
          try {
            // 通过异步函数 实现发送请求时，验证通过，同时执行路由的跳转，验证不通过，提示错误信息
            await this.$store.dispatch('login', {
              username: this.loginForm.username,
              password: this.loginForm.password
            })
            // this.token !== '' 从服务端返回来的唯一标识用户的识别码
            if (this.token !== '') {
              loadingInstance = loading.service({ fullscreen: true }) // 添加 loading效果
              // 2s 后关闭loading效果并进行路由跳转
              setTimeout(() => {
                loadingInstance.close() // 关闭loading

                // 给浏览 存储 token值 导航守卫放行
                // localStorage.setItem('token', this.token)

                //  记住密码功能  调用 setCookie 方法，并给浏览器保存 token值 这个token值是密码和用户名
                //  同时 导航守卫放行
                if (
                  this.loginForm.username !== '' &&
                  this.loginForm.password !== ''
                ) {
                  if (this.loginForm.state) {
                    let password = Base64.encode(this.loginForm.password) // base64加密
                    this.setCookie(this.loginForm.username, password, 7)
                  } else {
                    this.setCookie('', '', -1) // 修改2值都为空，天数为负1天就好了
                  }
                }

                // 这里清空的是从服务端返回来的 token值  用户唯一标识  不是浏览器的token值
                // 目的是为了防止上一次登录成功的 服务端token值保存到下一次登录
                this.clearToken()

                this.$router.push({
                  // 跳转的路由的 名称
                  name: 'home',
                  // 进行路由传参 并将用户信息进行路由传参
                  params: { keyword: this.loginForm.username || undefined }
                })
              }, 1500)
            } else {
              // 登录失败 移除 浏览器的 token值 导航守卫阻止跳转
              localStorage.removeItem('token')

              // 判断是否存在该用户
              if (this.user === true) {
                this.$message({
                  message: '用户名或者密码错误',
                  type: 'warning'
                })
              } else {
                this.$message.error('您还没有注册该账号呢，请先注册')
              }
            }
          } catch (error) {
            alert('捕获到发生未知错误')
          }
        }
      })
    }, 500),

    // 当用户登录成功后，调用vuex中的方法，清空token值，目的是为了防止下一次登录请求，浏览器中存在上一次的token值
    clearToken() {
      this.$store.commit('CLERATOKEN')
    },
    // 登录页面 点击注册按钮
    resetForm(formName) {
      // 请除登录表单的值和验证结果
      this.$refs[formName].resetFields()
      // 开启 对话框
      this.dialogVisible = true
    },

    // 给浏览设置cookie 保存 用户登录信息
    setCookie(username, password, days) {
      let date = new Date() // 获取时间
      date.setTime(date.getTime() + 24 * 60 * 60 * 1000 * days) // 保存的天数
      // 字符串拼接cookie
      window.document.cookie =
        'username' + '=' + username + ';path=/;expires=' + date.toGMTString()
      window.document.cookie =
        'password' + '=' + password + ';path=/;expires=' + date.toGMTString()
    },

    // 读取cookie 将用户名和密码回显到input框中
    getCookie() {
      if (document.cookie.length > 0) {
        let arr = document.cookie.split('; ') //分割成一个个独立的“key=value”的形式
        for (let i = 0; i < arr.length; i++) {
          let arr2 = arr[i].split('=') // 再次切割，arr2[0]为key值，arr2[1]为对应的value
          if (arr2[0] === 'username') {
            this.loginForm.username = arr2[1] // 用户名回显
          } else if (arr2[0] === 'password') {
            this.loginForm.password = Base64.decode(arr2[1]) // base64解密 密码回显
            this.loginForm.state = true
          }
        }
      }
    },

    // 注册对话框
    // 检测注册用户名和邮箱是否可用  设置了防抖
    examine: debounce(function () {
      // 如果表单验证不通过 不发送请求
      let nameReg = /^([a-zA-Z0-9_-]|[\u4E00-\u9FA5]){3,12}$/
      let emailReg = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/
      if (
        nameReg.test(this.registerForm.name) ||
        emailReg.test(this.registerForm.email)
      ) {
        // 将请求参数发送给服务端
        this.$store.dispatch('user', {
          username: this.registerForm.name,
          email: this.registerForm.email
        })
      }
    }, 50),

    //  验证码--生成随机数
    randomNum(min, max) {
      return Math.floor(Math.random() * (max - min) + min)
    },
    // 切换验证码
    refreshCode() {
      this.registerForm.identifyCode = ''
      this.makeCode(this.registerForm.identifyCodes, 4)
    },
    // 生成四位随机验证码
    makeCode(o, l) {
      for (let i = 0; i < l; i++) {
        this.registerForm.identifyCode +=
          this.registerForm.identifyCodes[
            this.randomNum(0, this.registerForm.identifyCodes.length)
          ]
      }
      console.log(this.registerForm.identifyCode)
    },
    // 注册页面的 注册用户按钮
    submitFormLabelAlign: throttle(function (registerForm) {
      this.$refs[registerForm].validate((valid) => {
        if (valid) {
          // 将用户注册成功的所有请求参数发送给服务端
          this.$store.dispatch('register', this.registerForm)
          this.$message({
            message: '恭喜你，注册成功了',
            type: 'success'
          })
          setTimeout(() => {
            // 清除注册表单的值和验证结果
            this.$refs[registerForm].resetFields()
            // 关闭注册对话框
            this.dialogVisible = false
          }, 1000)
        } else {
          // 注册失败 更换验证码
          this.refreshCode()
          this.$notify.error({
            title: '错误',
            message: '请正确注册用户'
          })
          return false
        }
      })
    }, 1000),
    // 当关闭注册对话框时
    onDialogClosed() {
      // 清空 整个 registerForm 表单的内容
      console.log('对话框关闭')
      this.$refs.registerForm.resetFields()
    }
  }
}
</script>

<style lang="less" scoped>
.text {
  font-size: 14px;
}

.item {
  padding: 18px 0;
}
.login {
  position: relative;
  width: 100%;
  height: 100%;
}
.box-card {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 480px;
}
</style>
